import { Prop } from 'vue-property-decorator'
import { AxiosResponse } from 'axios'
import { ComponentModel } from '@TG/interface'
import { IElFormPackage } from '@TG/interface/types/component'
import { showMessage, showConfirm } from '@TG/kit/element/message'
import { emptyResponse, validResponse } from '@TG/kit/request'
import { isEmpty, isNotEmpty } from '@TG/kit/validate'
import TgComponent from '../TgComponent'

/*
prop 列表
  title: string                                                           表单标题
  maxHeight: number                                                       表单最大高度 [默认为 -1，既未指定，各子类按实现需要处理默认值]
  holdHeight: boolean                                                     保持表单高度 [默认为 true]
  form: {
    linkage?: boolean                                                     [参考 ElFormPackage.@Prop.linkage]
    defaultModel?: any                                                    表单初始化默认 model
    formProps?: Map<string, any>                                       [参考 ComponentModel.props]
    formEvents?: Map<string, Function | Function[]>                    [参考 ComponentModel.events]
    handleFormModel?: (operate: string, model: any) => any                动态处理表单 model
    handleFormItems?: (operate: string, model: any) => ComponentModel[]   动态处理表单 items
    load?: (params: any) => Promise<AxiosResponse<any>>                   远程加载表单 model
    saveBefore?: (operate: string, model: any) => boolean                 保存表单前执行
    save?: (operate: string, model: any) => Promise<AxiosResponse<any>>   远程保存表单 model
    saveAfter?: (operate: string, model: any) => void                     保存表单后执行
  }
  controlBar: {
    leftItems?: ComponentModel[]                                          [参考 TgControlBar.@Prop.leftItems]
    rightItems?: ComponentModel[]                                         [参考 TgControlBar.@Prop.rightItems]
    showSave?: boolean                                                    是否显示保存按钮 [默认为 true]
    showReset?: boolean                                                   是否显示重置按钮 [默认为 true]
  }  控制 Bar prop 列表 [参考 TgcontrolBar]
ref 列表
  ref-form [默认]
*/
export default class extends TgComponent {
  @Prop({ type: String, default: '' }) protected title!: string
  @Prop({ type: Number, default: -1 }) protected maxHeight!: number
  @Prop({ type: Boolean, default: true }) protected holdHeight!: boolean
  @Prop({ type: Object, required: true }) protected form!: {
    linkage?: boolean
    defaultModel?: any
    formProps?: Map<string, any>
    formEvents?: Map<string, Function | Function[]>
    handleFormModel?: (operate: string, model: any) => any
    handleFormItems?: (operate: string, model: any) => ComponentModel[]
    load?: (params: any) => Promise<AxiosResponse<any>>
    saveBefore?: (operate: string, model: any) => boolean
    save?: (operate: string, model: any) => Promise<AxiosResponse<any>>
    saveAfter?: (operate: string, model: any) => void
  }
  @Prop({ type: Object }) protected controlBar!: {
    leftItems?: ComponentModel[]
    rightItems?: ComponentModel[]
    showSave?: boolean
    showReset?: boolean
  }

  protected operate: 'add' | 'edit' | 'view' = 'view'
  protected model: any = {}
  protected formItems: ComponentModel[] = []
  protected formResetTo: any = {}
  protected formLoading: boolean = false

  get formCM() {
    return {
      props: Object.assign({ model: this.model }, this.form.formProps || {}),
      events: this.form.formEvents || {},
      items: this.formItems
    }
  }

  get formLinkage() {
    return this.form.linkage || false
  }

  get defaultModel() {
    return this.form.defaultModel || {}
  }

  get handleFormModel() {
    const handleFormModel = this.form.handleFormModel
    if (isNotEmpty(handleFormModel)) {
      return handleFormModel as (operate: string, model: any) => any
    } else {
      return (operate: string, model: any) => model
    }
  }

  get handleFormItems() {
    const handleFormItems = this.form.handleFormItems
    if (isNotEmpty(handleFormItems)) {
      return handleFormItems as (operate: string, model: any) => ComponentModel[]
    } else {
      return (operate: string, model: any) => []
    }
  }

  get load() {
    const load = this.form.load
    if (isNotEmpty(load)) {
      return load as (params: any) => Promise<AxiosResponse<any>>
    } else {
      return (params: any) => Promise.resolve(emptyResponse({}))
    }
  }

  get saveBefore() {
    const saveBefore = this.form.saveBefore
    if (isNotEmpty(saveBefore)) {
      return saveBefore as (operate: any, model: any) => boolean
    } else {
      return (operate: any, model: any) => true
    }
  }

  get save() {
    const save = this.form.save
    if (isNotEmpty(save)) {
      return save as (operate: any, model: any) => Promise<AxiosResponse<any>>
    } else {
      return (operate: any, model: any) => Promise.resolve(emptyResponse(model))
    }
  }

  get saveAfter() {
    const saveAfter = this.form.saveAfter
    if (isNotEmpty(saveAfter)) {
      return saveAfter as (operate: any, model: any) => void
    } else {
      return (operate: any, model: any) => {}
    }
  }

  get hasControlBar() {
    return this.controlBarLeftItems.length > 0 || this.controlBarRightItems.length > 0
  }

  get controlBarLeftItems() {
    return this.controlBar?.leftItems || []
  }

  get controlBarRightItems() {
    const rightItems = []
    const showSave = this.controlBar?.showSave === undefined ? true : this.controlBar.showSave
    const showReset = this.controlBar?.showReset === undefined ? true : this.controlBar.showReset
    rightItems.push(...(this.controlBar?.rightItems || []))
    if (showSave) {
      rightItems.push({
        tag: 'el-button-package',
        text: '保  存',
        props: { type: 'primary', icon: 'el-icon-antd-save' },
        events: { click: () => this.saveModel() }
      })
    }
    if (showReset) {
      rightItems.push({
        tag: 'el-button-package',
        text: '重  置',
        props: { icon: 'el-icon-antd-undo' },
        events: { click: () => this.resetForm() }
      })
    }
    return rightItems
  }

  protected formRef(): IElFormPackage {
    return this.ref() as IElFormPackage
  }

  public handleFormInput(model: any) {
    this.model = this.handleFormModel(this.operate, model)
    this.formItems = this.handleFormItems(this.operate, this.model)
    this.$emit('input', this.model)
  }

  public initForm(operate: 'add' | 'edit' | 'view', params?: any, dynamicModel?: any) {
    this.operate = operate
    if (this.operate === 'add' || (this.operate === 'view' && isEmpty(params))) {
      this.formLoading = true
      this.model = Object.assign({}, this.defaultModel, dynamicModel)
      this.formResetTo = this.model
      this.formItems = this.handleFormItems(this.operate, this.model)
      this.formLoading = false
    } else if ((this.operate === 'edit' || this.operate === 'view') && isNotEmpty(params)) {
      this.formLoading = true
      this.load(params).then(response => {
        if (validResponse(response)) {
          const model = response.data
          if (isNotEmpty(model)) {
            this.model = model
          } else {
            this.model = Object.assign({}, this.defaultModel, params, dynamicModel)
          }
          this.formResetTo = this.model
          this.formItems = this.handleFormItems(this.operate, this.model)
        }
        this.formLoading = false
      })
    } else if (this.operate === 'edit' && isEmpty(params)) {
      showMessage('编辑表单请指定入参', 'error')
    }
  }

  public saveModel() {
    this.formRef().validateForm().then(valid => {
      if (valid) {
        let model = this.getModel()
        let boole = this.saveBefore(this.operate, model)
        if (boole) {
          this.formLoading = true
          this.save(this.operate, model).then(response => {
            if (validResponse(response)) {
              model = response.data
              this.model = model
              this.formResetTo = model
              this.saveAfter(this.operate, model)
            }
            this.formLoading = false
          })
        }
      }
    })
  }

  public getModel() {
    const ref = this.formRef()
    if (isNotEmpty(ref)) {
      return ref.getModel()
    } else {
      return {}
    }
  }

  public clearValidate() {
    const ref = this.formRef()
    if (isNotEmpty(ref)) {
      ref.clearValidate()
    }
  }

  public validateForm() {
    const ref = this.formRef()
    if (isNotEmpty(ref)) {
      return ref.validateForm()
    } else {
      return Promise.resolve(false)
    }
  }

  public clearForm() {
    const ref = this.formRef()
    if (isNotEmpty(ref)) {
      ref.clearForm()
    }
  }

  public resetForm() {
    showConfirm('是否重置表单 ？', 'warning').then(() => {
      const ref = this.formRef()
      if (isNotEmpty(ref)) {
        ref.resetForm()
      }
    })
  }

  public defaultRef() {
    return 'form'
  }
}
